﻿using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using Windows.ApplicationModel.Core;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Xaml.Media;
using FunstreamTV.Model.Chat;
using FunstreamTV.ViewModel.ObjectViewModel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SocketIoClientDotNet.Client;
using SocketIoClientDotNet.EngineIO.ComponentEmitter;
using SocketIoClientDotNet.EngineIO.Quobject.Collections.Immutable;

namespace FunstreamTV.Tools
{
    public class SocketIOHelper
    {
        public event EventHandler MessageAdded;
        public Socket socket;
        private Emitter emitter;
        public ObservableCollection<ChatMessageViewModel> Messages { get; set; }

        public SocketIOHelper()
        {
            socket = IO.Socket("http://funstream.tv:3811", new IO.Options { Transports = ImmutableList.Create("websocket") });
        }

        public void Connect(string token, string streamID)
        {
            emitter = socket.On(Socket.EVENT_CONNECT, (a) =>
            {
                socket.Emit("/chat/login", (b) => { }, new JObject {["token"] = token });

                socket.Emit("/chat/join", (b) => { }, new JObject {["channel"] = "stream/" + streamID });

                socket.Emit("/chat/history", async (b) =>
                {
                    var chatResponse = Serializer.Deserialize<ChatResponse<ObservableCollection<ChatMessage>>>(b.ToString());

                    if (chatResponse != null)
                        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                        {
                            Messages = new ObservableCollection<ChatMessageViewModel>(chatResponse.result.Select(i => new ChatMessageViewModel
                            {
                                channel = i.channel,
                                text = i.text,
                                time = i.time,
                                to = i.to,
                                from = i.from,
                                id = i.id
                            }));
                            if (Messages.Count != 0)
                                MessageAdded?.Invoke(this, new EventArgs());
                        });
                }, new JObject { { "channel", "stream/" + streamID }, { "amount", 100} });
            });

            socket.On(Socket.EVENT_CONNECT_ERROR, (b) =>
            {
                Debug.WriteLine(b);
            });

            socket.On("/chat/message", async (b) =>
            {
                var chatMessage = Serializer.Deserialize<ChatMessage>(b.ToString());

                if (chatMessage != null)
                    await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        Messages.Add(new ChatMessageViewModel
                        {
                            channel = chatMessage.channel,
                            text = chatMessage.text,
                            time = chatMessage.time,
                            to = chatMessage.to,
                            from = chatMessage.from,
                            id = chatMessage.id
                        });
                        MessageAdded?.Invoke(this, new EventArgs());
                    });
            });

            socket.On("/chat/user/leave", async (b) =>
            {
                var leaveMessage = JsonSerializer.Create().Deserialize<Leave>(new JTokenReader(b as JObject));
                await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    Messages.Add(new ChatMessageViewModel
                    {
                        text = "Пользователь" + leaveMessage.id + "покинул канал",
                        from = new ChatFrom { name = "system", namecolor = 0 },
                        time = DateTime.Now.ToString()
                    });
                    MessageAdded?.Invoke(this, new EventArgs());
                });
            });

            socket.On("/chat/message/remove", async (b) =>
            {
                var removeObject = JsonSerializer.Create().Deserialize<Remove>(new JTokenReader(b as JObject));
                await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    var message = Messages.FirstOrDefault(i => i.id.Equals(removeObject.id));
                    if (message != null)
                        Messages.Remove(message);
                });
            });
        }

        public void SendMessage(JObject jobject)
        {
            socket.Emit("/chat/publish", (b) => { }, jobject);
        }
    }
}